package com.fly.core.config;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ValidationException;

import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import com.fly.core.entity.JsonResult;

import lombok.extern.slf4j.Slf4j;

/**
 * 异常处理
 *
 * @author jack
 */
@ControllerAdvice
@Slf4j
@ResponseBody
public class GlobalExceptionHandler
{
    
    @ExceptionHandler(Exception.class)
    public JsonResult<?> exception(HttpServletRequest request, Exception e)
    {
        log.error("异常请求 {} {}", request.getRemoteAddr(), request.getRequestURI(), e);
        return JsonResult.error("服务异常");
    }
    
    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public JsonResult<?> handlerValidationException(HttpServletRequest request, ValidationException e)
    {
        logError(request, e);
        return JsonResult.error(e.getMessage());
    }
    
    @ExceptionHandler(BindException.class)
    public JsonResult<?> handlerParamException(HttpServletRequest request, BindException e)
    {
        logError(request, e);
        FieldError error = e.getBindingResult().getFieldError();
        return JsonResult.error("请求失败" + (null == error ? "" : ": " + error.getField() + " " + error.getDefaultMessage()));
    }
    
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public JsonResult<?> handleMethodArgTypeMismatch(HttpServletRequest request, MethodArgumentTypeMismatchException e)
    {
        logError(request, e);
        return JsonResult.error("请求失败,参数：" + e.getName() + " 类型错误");
    }
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public JsonResult<?> HandleValidationException(HttpServletRequest request, MethodArgumentNotValidException e)
    {
        logError(request, e);
        FieldError error = e.getBindingResult().getFieldError();
        return JsonResult.error("请求失败" + (null == error ? "" : ": " + error.getField() + " " + error.getDefaultMessage()));
    }
    
    @ExceptionHandler(HttpMessageConversionException.class)
    @ResponseBody
    public JsonResult<?> HandleConversionException(HttpServletRequest request, HttpMessageConversionException e)
    {
        logError(request, e);
        return JsonResult.error("请求失败: 请求解析异常");
    }
    
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public JsonResult<?> handleMissingParam(HttpServletRequest request, MissingServletRequestParameterException e)
    {
        logError(request, e);
        return JsonResult.error("缺少参数: " + e.getParameterName() + " (" + e.getParameterType() + ")");
    }
    
    @ExceptionHandler(ServletException.class)
    @ResponseBody
    public JsonResult<?> handleServletException(HttpServletRequest request, ServletException e)
    {
        logError(request, e);
        return JsonResult.error(e.getMessage());
    }
    
    private static void logError(HttpServletRequest request, Exception e)
    {
        log.error("异常请求 {} {} {} {}", request.getRemoteAddr(), request.getRequestURI(), e.getClass(), e.getMessage());
    }
    
}
